﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace DMA.SGDB.Util
{
    public class Encryption
    {
        // Encryption
        //PlainText  = Text to be encrypted
        //Password  = Password to encrypt with
        //Salt  = Salt to encrypt with
        //HashAlgorithm  = Can be either SHA1 or MD5
        //PasswordIterations  = Number of iterations to do
        //InitialVector  = Needs to be  ASCII characters long
        //KeySize  = Can be , , or 

        public static string Encryptstring(string PlainText, string Password, string Salt = "Maddyencrypt",
                                            string HashAlgorithm = "MD5", int PasswordIterations = 2,
                                            string InitialVector = "ghVNHfg544JUdfjdY5BGVbj67", int KeySize = 256)
        {
            if (string.IsNullOrEmpty(PlainText))
                return "";

            byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
            byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
            byte[] PlainTextBytes = Encoding.UTF8.GetBytes(PlainText);

            PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);

            byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);

            RijndaelManaged SymmetricKey = new RijndaelManaged();
            SymmetricKey.Mode = CipherMode.ECB;

            byte[] CipherTextBytes = null;

            using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes))
            {
                using (MemoryStream MemStream = new MemoryStream())
                {
                    using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write))
                    {
                        CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
                        CryptoStream.FlushFinalBlock();
                        CipherTextBytes = MemStream.ToArray();
                        MemStream.Close();
                        CryptoStream.Close();
                    }
                }
            }

            SymmetricKey.Clear();

            return Convert.ToBase64String(CipherTextBytes); // returns a encrypted string
        }

        // Decryption
        //CipherText  = Text to be decrypted
        //Password  = Password to decrypt with
        //Salt  = Salt to decrypt with
        //HashAlgorithm  = Can be either SHA1 or MD5
        //PasswordIterations  = Number of iterations to do
        //InitialVector  = Needs to be  ASCII characters long
        //KeySize  = 128, 192, or 256 

        public static string Decryptstring(string CipherText, string Password, string Salt = "Maddyencrypt",
                                            string HashAlgorithm = "MD5", int PasswordIterations = 2,
                                            string InitialVector = "ghVNHfg544JUdfjdY5BGVbj67", int KeySize = 256)
        {
            if (string.IsNullOrEmpty(CipherText))
                return "";

            byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
            byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
            byte[] CipherTextBytes = Convert.FromBase64String(CipherText);

            PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);

            byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);

            RijndaelManaged SymmetricKey = new RijndaelManaged();
            SymmetricKey.Mode = CipherMode.ECB;

            byte[] PlainTextBytes = new byte[CipherTextBytes.Length];

            int ByteCount = 0;

            using (ICryptoTransform Decryptor = SymmetricKey.CreateDecryptor(KeyBytes, InitialVectorBytes))
            {
                using (MemoryStream MemStream = new MemoryStream(CipherTextBytes))
                {
                    using (CryptoStream CryptoStream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read))
                    {
                        ByteCount = CryptoStream.Read(PlainTextBytes, 0, PlainTextBytes.Length);
                        MemStream.Close();
                        CryptoStream.Close();
                    }
                }
            }

            SymmetricKey.Clear();

            return Encoding.UTF8.GetString(PlainTextBytes, 0, ByteCount); // returns decrypted string
        }
    }
}
